import math

from django.core import serializers
from django.http import HttpResponse, JsonResponse

from BusinessSubSystem.algorithmFunction import get_weight_by_ahp, get_fund_sorted_result
from BusinessSubSystem.constUtils import CONST_SCHEME_ONE
from BusinessSubSystem.models import fundField
import json

from BusinessSubSystem.notSaveInDataBaseModel import UserChoiceSingleton, FundListSingleton
from UserSubSystem.models import fundPlan


def receive_form(request):
    '''
    接收用户上传的表单
    :param request: 发送上来的请求表单
    :return: 响应成功与否
    '''
    user_form = json.loads(request.POST.get("user_form"))
    # try:
    user_choice_save_model = UserChoiceSingleton.get_instance()
    print(user_choice_save_model)
    user_choice_save_model.create_user_choice(user_form)
    # except Exception as e:
    #     print("ERROR, exception caught!Detail is: %s" % e)
    data = {'data': 'success', 'flag': True}
    return JsonResponse(data)

def get_all_fund_field(request):
    '''
    :param request: 验证请求,待后续开发
    :return: 返回投资领域列表
    返回去掉了基金相关领域中的“其他”领域，因为这是基金所涉及的一些小领域
    '''
    all_fund_field = fundField.objects.exclude(fund_field_name="其他")
    flag = False
    data = {'data': '', 'flag': flag}
    if len(all_fund_field) > 0:
        flag = True
        return_object = list(all_fund_field)
        return_json = serializers.serialize("json", return_object)
        data['data'] = return_json
        data['flag'] = flag
    return JsonResponse(data)

def get_expected_rate(request):
    '''
        获取用户的选择并返回计算过的预期收益率
        :param request: 请求中含有user_id
        :return: 返回计算过的收益率
    '''
    user_id = request.GET.get("user_id")
    user_choice_save_model = UserChoiceSingleton.get_instance()
    user_choice = user_choice_save_model.get_user_choice(user_id)
    return_data = {
        "max_expected_return": float(user_choice["user_expected_return"]) * 1.5,
        "min_expected_return": float(user_choice["user_expected_return"]) * 0.5,
        "user_expected_time" : user_choice["user_expected_time"]
    }
    flag = True
    return_obj = {
        "data" : [return_data],
        "flag" : flag
    }
    return JsonResponse(return_obj)

def adjust_risk_assets_rate(request):
    '''
    获取用户的风险资产占比
    :param request:来自用户的请求
    :return:成功的标识符
    '''
    user_adjust_risk_assets_rate_form = json.loads(request.POST.get("user_adjust_risk_assets_rate_form"))
    try:
        user_choice_save_model = UserChoiceSingleton.get_instance()
        user_choice_save_model.create_user_risk_degree_choice(user_adjust_risk_assets_rate_form)
    except Exception as e:
        print("ERROR, exception caught!Detail is: %s" % e)
    data = {'data': 'success', 'flag': True}
    return JsonResponse(data)

def get_scheme_one(request):
    '''
    这个偏重于考虑用户选择的领域,从"3344"法则筛选出的基金的排名前十的基金进行返回
    :param request: 包含有user_id的请求
    :return: 方案一对应的基金列表
    '''
    user_id = request.GET.get("user_id")
    user_choice_singleton = UserChoiceSingleton.get_instance()
    user_self_choice = user_choice_singleton.get_user_choice(user_id)
    user_risk_choice = user_choice_singleton.get_user_risk_degree_choice(user_id)
    user_risk_degree = user_risk_choice["user_risk_ratio"] * 10
    # 股票型基金的数目 = 用户风险资产占比向上取整
    stock_fund_number = math.ceil(user_risk_degree)
    # 债券型基金的数目 = 决定在方案一中返回的基金数目 - 股票型基金的数目
    bond_fund_number = CONST_SCHEME_ONE - stock_fund_number
    user_year = user_self_choice["user_expected_time"]
    fund_list_singleton = FundListSingleton.get_instance()

    # 这是"4433"法则筛选过的基金集合
    stock_fund_to_field_list = fund_list_singleton.get_risk_list(year=user_year)
    bond_fund_list = fund_list_singleton.get_bond_list(year=user_year)
    weight = get_weight_by_ahp(user_id)
    bond_fund = get_fund_sorted_result(bond_fund_list,weight)
    stock_fund_field_list = []
    stock_fund = []
    # 判断这只股票是否已经被放入集合中去了
    is_selected_field_map = {}
    # 筛选一下根据用户选择领域筛选出的基金集合
    for each_stock_fund_to_field in stock_fund_to_field_list:
        if each_stock_fund_to_field.fund_field_id_id in user_self_choice["fund_field"]:
            try:
                is_selected_field_map[each_stock_fund_to_field.fund_id.fund_code]
            except Exception:
                is_selected_field_map[each_stock_fund_to_field.fund_id.fund_code] = True
                stock_fund_field_list.append(each_stock_fund_to_field.fund_id)

    print(len(stock_fund_field_list))
    print(stock_fund_number)
    if len(stock_fund_field_list) > stock_fund_number:
        stock_fund = get_fund_sorted_result(stock_fund_field_list, weight)
    else:
        stock_fund_list = []
        # 判断这只股票是否已经被放入集合中去了
        is_selected_map = {}
        # 筛选一下股票集合
        for each_stock_fund_to_field in stock_fund_to_field_list:
            flag = True
            for each_stock in stock_fund_field_list:
                if each_stock.fund_code == each_stock_fund_to_field.fund_id.fund_code:
                    flag = False
                    break

            if flag:
                try:
                    is_selected_map[each_stock_fund_to_field.fund_id.fund_code]
                except Exception as e:
                    is_selected_map[each_stock_fund_to_field.fund_id.fund_code] = True
                    stock_fund_list.append(each_stock_fund_to_field.fund_id)

        stock_fund.extend(stock_fund_list)

    return_fund_list = bond_fund[:bond_fund_number] + stock_fund[:stock_fund_number]
    return_data = []
    # 这是根据打分的多少决定投入的占比
    total_score = 0
    for each_fund in return_fund_list:
        total_score += each_fund["fund_score"]

    for each_fund in return_fund_list:
        fund_obj = {
            "fund_id":each_fund["fund"].id,
            "fund_code": each_fund["fund"].fund_code,
            "fund_name":each_fund["fund"].fund_name,
            "fund_proportion":each_fund["fund_score"]/total_score,
            "fund_type":each_fund["fund"].fund_type,
            "volatility_rank_1y":each_fund["fund"].volatility_rank_1y,
            "sharpe_rank_1y":each_fund["fund"].sharpe_rank_1y,
            "max_draw_down_1y":each_fund["fund"].max_draw_down_1y,
            "volatility_rank_3y": each_fund["fund"].volatility_rank_3y,
            "sharpe_rank_3y": each_fund["fund"].sharpe_rank_3y,
            "max_draw_down_3y": each_fund["fund"].max_draw_down_3y,
        }
        return_data.append(fund_obj)

    flag = True
    return_obj = {
        "data": return_data,
        "flag": flag
    }
    return JsonResponse(return_obj)

def get_scheme_two(request):
    '''
    取得问卷对应的权重,从"3344"法则筛选出的基金的排名前十的基金进行返回
    :param request: 包含有user_id的请求
    :return: 方案一对应的基金列表
    '''
    user_id = request.GET.get("user_id")
    user_choice_singleton = UserChoiceSingleton.get_instance()
    user_self_choice = user_choice_singleton.get_user_choice(user_id)
    user_risk_choice = user_choice_singleton.get_user_risk_degree_choice(user_id)
    user_risk_degree = user_risk_choice["user_risk_ratio"] * 10
    # 股票型基金的数目 = 用户风险资产占比向上取整
    stock_fund_number = math.ceil(user_risk_degree)
    # 债券型基金的数目 = 决定在方案一中返回的基金数目 - 股票型基金的数目
    bond_fund_number = CONST_SCHEME_ONE - stock_fund_number
    user_year = user_self_choice["user_expected_time"]
    fund_list_singleton = FundListSingleton.get_instance()

    # 这是"4433"法则筛选过的基金集合
    stock_fund_to_field_list = fund_list_singleton.get_risk_list(year=user_year)
    bond_fund_list = fund_list_singleton.get_bond_list(year=user_year)
    weight = get_weight_by_ahp(user_id)
    bond_fund = get_fund_sorted_result(bond_fund_list,weight)
    stock_fund_list = []
    # 判断这只股票是否已经被放入集合中去了
    is_selected_map = {}
    # 筛选一下股票集合
    for each_stock_fund_to_field in stock_fund_to_field_list:
        try:
            is_selected_map[each_stock_fund_to_field.fund_id.fund_code]
        except Exception as e:
            is_selected_map[each_stock_fund_to_field.fund_id.fund_code] = True
            stock_fund_list.append(each_stock_fund_to_field.fund_id)

    stock_fund = get_fund_sorted_result(stock_fund_list,weight)
    return_fund_list = bond_fund[:bond_fund_number] + stock_fund[:stock_fund_number]
    return_data = []
    # 这是根据打分的多少决定投入的占比
    total_score = 0
    for each_fund in return_fund_list:
        total_score += each_fund["fund_score"]

    for each_fund in return_fund_list:
        fund_obj = {
            "fund_id":each_fund["fund"].id,
            "fund_code": each_fund["fund"].fund_code,
            "fund_name":each_fund["fund"].fund_name,
            "fund_proportion":each_fund["fund_score"]/total_score,
            "fund_type":each_fund["fund"].fund_type,
            "volatility_rank_1y":each_fund["fund"].volatility_rank_1y,
            "sharpe_rank_1y":each_fund["fund"].sharpe_rank_1y,
            "max_draw_down_1y":each_fund["fund"].max_draw_down_1y,
            "volatility_rank_3y": each_fund["fund"].volatility_rank_3y,
            "sharpe_rank_3y": each_fund["fund"].sharpe_rank_3y,
            "max_draw_down_3y": each_fund["fund"].max_draw_down_3y,
        }
        return_data.append(fund_obj)

    flag = True
    return_obj = {
        "data": return_data,
        "flag": flag
    }
    return JsonResponse(return_obj)


def get_user_fund_plan(request):
    user_id = request.POST.get("user_id")
    fund_plan_list = json.loads(request.POST.get("fund_plan_list"))
    fund_deleted_list = fundPlan.objects.filter(user_id_id=user_id).all()
    fund_deleted_list.delete()
    for each_fund in fund_plan_list:
        ready_to_save_fund = fundPlan()
        ready_to_save_fund.fund_id_id = each_fund["fund_id"]
        ready_to_save_fund.fund_proportion = each_fund["fund_proportion"]
        ready_to_save_fund.user_id_id = user_id
        ready_to_save_fund.save()
    flag = True
    return_obj = {
        "data": "success",
        "flag": flag
    }
    return JsonResponse(return_obj)
